%include "pm.inc"
%include "load.inc"
bits 16
org 0
jmp start
cstart:
	incbin "c.bin",($-$$) ;在这里嵌入C程序

; GDT ------------------------------------------------------------------------------------------------------------------------------------------------------------
;                                                段基址            段界限     , 属性
LABEL_GDT:			Descriptor             0,                    0, 0						; 空描述符
LABEL_DESC_FLAT_C:		Descriptor             0,              0fffffh, DA_CR  | DA_32 | DA_LIMIT_4K			; 0 ~ 4G
LABEL_DESC_FLAT_RW:		Descriptor             0,              0fffffh, DA_DRW | DA_32 | DA_LIMIT_4K			; 0 ~ 4G
LABEL_DESC_VIDEO:		Descriptor	 0B8000h,               0ffffh, DA_DRW                         | DA_DPL3	; 显存首地址
; GDT ------------------------------------------------------------------------------------------------------------------------------------------------------------

GdtLen		equ	$ - LABEL_GDT
GdtPtr		dw	GdtLen - 1				; 段界限
		dd	LOADER_PHY_ADDR + LABEL_GDT		; 基地址 (让基地址八字节对齐将起到优化速度之效果，目前懒得改)
; The GDT is not a segment itself; instead, it is a data structure in linear address space.
; The base linear address and limit of the GDT must be loaded into the GDTR register. -- IA-32 Software Developer’s Manual, Vol.3A


; GDT 选择子 ----------------------------------------------------------------------------------
SelectorFlatC		equ	LABEL_DESC_FLAT_C	- LABEL_GDT
SelectorFlatRW		equ	LABEL_DESC_FLAT_RW	- LABEL_GDT
SelectorVideo		equ	LABEL_DESC_VIDEO	- LABEL_GDT + SA_RPL3
; GDT 选择子 ----------------------------------------------------------------------------------


BaseOfStack	equ	0100h

%include "invoke.inc"


_MemChkBuf:	times	0200h	db	0
_dwMCRNumber:			dd	0	; Memory Check Result
szMemChkMsg	db	'Memory check',0
szMemChkFail	db	'Fail!',0DH,0AH,0
szMemChkOK	db	'Ok! Total Memory Size=',0
szDot		db	'.',0

szBaseAddress	db	'Base:0x',0
szSizeInBytes	db	' Size:0x',0
szType		db	' Type:',0

szEndLine	db	0DH,0AH,0
dwMemorySize	dd	0


%MACRO print_word 2
	push ax
	mov ax, %2
	shr ax, 8
	invoke print_hex, %1, ax
	mov ax, %2
	invoke print_hex, %1, ax
	pop ax
%ENDM

%MACRO print_dword 2
	push eax
	mov eax, %2
	shr eax, 24
	invoke print_hex, %1, ax
	mov eax, %2
	shr eax, 16
	invoke print_hex, %1, ax
	mov eax, %2
	shr eax, 8
	invoke print_hex, %1, ax
	mov eax, %2
	invoke print_hex, %1, ax
	pop eax
%ENDM

start:
	invoke print,0fh,LOADER_INFO
	invoke print,07h,szMemChkMsg



	;qword base address
	;qword base size in bytes
	;dword type -+- 01h available to OS
	;            +- other reserved
		; 得到内存数
	xor	ebx,ebx			; ebx = 后续值, 开始时需为 0
	mov	ax,ds;
	mov	es,ax
	mov	di,_MemChkBuf		; es:di 指向一个地址范围描述符结构（Address Range Descriptor Structure）
.MemChkLoop:
	mov	eax, 0E820h		; eax = 0000E820h
	mov	ecx, 20			; ecx = 地址范围描述符结构的大小
	mov	edx, 0534D4150h		; edx = 'SMAP'
	int	15h			; int 15h
	jc	.MemChkFail
	invoke	print,7, szEndLine

	invoke print,7,szBaseAddress
	print_dword 7, dword [es:di+4]
	print_dword 0fh, dword [es:di]

	invoke print,7,szSizeInBytes
	print_dword 0fh, dword [es:di+12]
	print_dword 7, dword [es:di+8]

	invoke print,7,szType
	movzx ax, byte [es:di+16]
	invoke print_hex,0fh, ax

	cmp byte [es:di+16],1
	jne .next
	push eax
	push edx
	mov edx, dword [es:di+8]
	mov eax, dword [dwMemorySize]
	add eax, edx
	mov dword [dwMemorySize], eax

.next:

	add	di, 20
	inc	dword [_dwMCRNumber]	; dwMCRNumber = ARDS 的个数
	cmp	ebx, 0
	jne	.MemChkLoop
	jmp	.MemChkOK
.MemChkFail:
	mov	dword [_dwMCRNumber], 0
	invoke print,04h,szMemChkFail
	jmp end
.MemChkOK:
	invoke	print,7, szEndLine

	invoke print,02h,szMemChkOK
	print_dword 2, [dwMemorySize]
	invoke	print,7, szEndLine
	push _MemChkBuf
	call cstart
	jmp end



	jmp end
buf_test db 0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh


LOADER_INFO		db	'Neocs Loader',0DH,0AH,0
STAGE2		db	'this is from loader.bin:Stage2',0DH,0AH,0
dwTest	dd 0x1234

;putc(byte color,byte char);
putc:
	enter 0,0
	push bx
	mov ah,0eh
	mov al,[bp+6]
	movzx bx, byte[bp+4]
	int 10h
	pop bx
	leave

ret 4

;print(byte color,char* str);
print:
	enter 0,0
	push bx
	push si
	movzx bx, byte[bp+4]
	mov si, [bp+6]
.ploop:
	mov ah,0eh
	mov al,[si]
	test al,al
	jz .break
	inc si
	int 10h
	jmp short .ploop
.break:
	pop si
	pop bx

	leave

ret 4

;print_buf(byte color,byte* str,word size);
print_buf:
	enter 0,0
	push cx
	push bx
	push si
	movzx bx,byte[bp+4]
	mov si,[bp+6]
	mov cx,[bp+8] ;size
.ploop:
	mov al,[si]
	inc si
	invoke print_hex,bx,ax
	dec cx
	test cx,cx
	jz .break
	jmp short .ploop
.break:
	pop si
	pop bx
	pop cx
	leave
ret 6

;print_hex(byte color,byte hex);
hex_tab: db '0123456789ABCDEF'
print_hex:
	enter 0,0
	push bx
	push si
	movzx ax,byte[bp+6]
	shr ax,4
	and ax,0fh
	add ax,hex_tab
	mov si,ax
	mov al,[si]
	movzx bx,byte[bp+4]
	mov ah,0eh
	int 10h
	movzx ax,byte[bp+6]
	and ax,0fh
	add ax,hex_tab
	mov si,ax
	mov al,[si]
	movzx bx,byte[bp+4]
	mov ah,0eh
	int 10h
	pop si
	pop bx
	leave

ret 4


end:
	hlt
	jmp short end
